[POWERPC][XEN] Enable in-guest performance monitoring.
authorHollis Blanchard <hollisb@us.ibm.com>
Fri, 13 Jul 2007 22:28:15 +0000 (17:28 -0500)
committerHollis Blanchard <hollisb@us.ibm.com>
Fri, 13 Jul 2007 22:28:15 +0000 (17:28 -0500)
- Lazily save and restore the performance monitor counters when switching
  domains.
- Control with the H_PERFMON PAPR hypercall.
- Ignore guest perfmon exceptions that land in Xen.
Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
xen/arch/powerpc/exceptions.h
xen/arch/powerpc/of_handler/papr.S
xen/arch/powerpc/papr/Makefile
xen/arch/powerpc/papr/h_perfmon.c [new file with mode: 0644]
xen/arch/powerpc/powerpc64/domain.c
xen/arch/powerpc/powerpc64/exceptions.S
xen/include/asm-powerpc/domain.h
xen/include/asm-powerpc/papr.h
xen/include/asm-powerpc/processor.h
xen/include/asm-powerpc/reg_defs.h
xen/include/asm-powerpc/xenoprof.h

index 7a71faee8def7187049ec2d847b70aa16a26d340..2b294ce94ec93c7bd22292dae73dbb0ac0036df5 100644 (file)
@@ -13,7 +13,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2005
+ * Copyright IBM Corp. 2005, 2007
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  */
@@ -39,6 +39,7 @@ extern  multiboot_info_t *boot_of_init(ulong r3, ulong r4, ulong vec, ulong r6,
 
 extern void do_timer(struct cpu_user_regs *regs);
 extern void do_dec(struct cpu_user_regs *regs);
+extern void do_perfmon(struct cpu_user_regs *regs);
 extern void program_exception(
     struct cpu_user_regs *regs, unsigned long cookie);
 
index 16ba6cfed479f4808cd838b6fc4004fae6994f21..9f979f0da348bc77898f3bf3809836e717a538e3 100644 (file)
@@ -67,7 +67,7 @@ PAPR(5, 1,papr_real_to_logical, H_REAL_TO_LOGICAL)
 PAPR(5, 1,papr_pci_config_read, H_PCI_CONFIG_READ)
 PAPR(5, 0,papr_pci_config_write, H_PCI_CONFIG_WRITE)
 
-       PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL)
+PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL)
 PAPR(1, 1,papr_accept_logical, H_ACCEPT_LOGICAL)
 PAPR(0, 2,papr_rescind_logical, H_RESCIND_LOGICAL)
 PAPR(3, 0,papr_register_vterm, H_REGISTER_VTERM)
index 8ea5183d3f7bb6fa0aa8f068893b202e6b58eb90..f1ba02c6ac62118e8b216ee237ab19d5b9e89850 100644 (file)
@@ -8,3 +8,4 @@ obj-y += tce.o
 obj-y += vtce.o
 obj-$(papr_vterm) += vterm.o
 obj-y += xlate.o
+obj-y += h_perfmon.o
diff --git a/xen/arch/powerpc/papr/h_perfmon.c b/xen/arch/powerpc/papr/h_perfmon.c
new file mode 100644 (file)
index 0000000..33de44f
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ */
+#undef DEBUG
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/init.h>
+#include <xen/domain.h>
+#include <public/xen.h>
+#include <asm/current.h>
+#include <asm/msr.h>
+#include <asm/papr.h>
+#include <asm/hcalls.h>
+#include <asm/xenoprof.h>
+
+#define H_PERFMON_ENABLE (1UL << 63)
+#define H_PERFMON_THRESHOLDGRANULARITY (1UL << 62)
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/* FIXME workaround - these are just the default values, need the values set to
+ * linux via sysfs up-to-date. */
+int pmc_reset_val[NUM_PMCS] = { (0x8000000-0x0),
+                                (0x8000000-0x100000),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0),
+                                (0x8000000-0x0)};
+int perf_count_active_vcpu;
+perf_sprs_t perf_clear_sprs;
+static DEFINE_SPINLOCK(perf_pmu_lock);
+
+static inline int has_pmu(void) { return 1; }
+
+void do_perfmon(struct cpu_user_regs *regs)
+{
+    ulong mmcra = mfmmcra();
+    ulong mmcr0 = mfmmcr0();
+    int pmc,i;
+    
+    if ((mmcra & MMCRA_SAMPHV) && !(mmcra & MMCRA_SAMPPR)) {
+        /* TODO Hypervisor sample - support to sample xen, 
+         * pass the sample to the primary sampling domain via an event channel.
+         */
+        printk("do_perfmon - called with sample of xen space\n");
+        print_perf_status();
+        BUG();
+    } 
+
+    /* Dom sample postponed into xen space
+     * Currently just ignored (decreases accuracy) 
+     * TODO pass the Dom samples to the appropriate domain via an event channel
+     * TODO get access to the real pmc_reset_val currently used by the domain
+     * to reset counter safe and valid
+     */
+
+    for (i = 0; i < NUM_PMCS; ++i) {
+        pmc = ctr_read(i);
+        if (pmc < 0) {
+            DBG("postponed perfmon exception - PMC%d < 0 - reset to default "
+                "'0x%0x'\n", i, pmc_reset_val[i]);
+            ctr_write(i,pmc_reset_val[i]);
+        }
+    }
+
+    mmcr0 |= MMCR0_PMAE;
+    mmcr0 &= ~MMCR0_FC;
+    mtmmcr0(mmcr0);
+}
+
+static void h_perfmon(struct cpu_user_regs *regs)
+{
+    ulong mode_set   = regs->gprs[4];
+    ulong mode_reset = regs->gprs[5];
+    struct vcpu *v = get_current();
+    struct domain *d = v->domain;
+
+    if (!has_pmu()) {
+        regs->gprs[3] = H_Function;
+        return;
+    }
+
+    /* only bits 0&1 are supported by H_PERFMON */
+    if (((mode_set | mode_reset) & ~(H_PERFMON_ENABLE |
+            H_PERFMON_THRESHOLDGRANULARITY)) != 0) {
+        regs->gprs[3] = H_Parameter;
+        return;
+    }
+    /* enable or disable it, not both */
+    if ((mode_set & mode_reset) != 0) {
+        regs->gprs[3] = H_Resource;
+        return;
+    }
+
+    spin_lock(&perf_pmu_lock);
+    if (mode_set & H_PERFMON_ENABLE) {
+        if (v->arch.pmu_enabled) {
+            DBG("H_PERFMON call on already enabled PMU for domain '%d' on "
+                "vcpu '%d'\n", d->domain_id, v->vcpu_id);
+            goto success;
+        }
+
+        if (!perf_count_active_vcpu) {
+           save_pmc_sprs(&perf_clear_sprs);
+#ifdef DEBUG
+           DBG("H_PERFMON Saved initial clear performance special purpose "
+               "registers\n");
+           print_perf_status();
+#endif
+        }
+        v->arch.pmu_enabled = 1;
+        perf_count_active_vcpu++;
+        printk("H_PERFMON call enabled PMU for domain '%d' on vcpu '%d'\n",
+                d->domain_id, v->vcpu_id);
+    } else if (mode_reset & H_PERFMON_ENABLE) {
+        if (!v->arch.pmu_enabled) {
+            DBG("H_PERFMON call on already disabled PMU for domain '%d' on "
+                "vcpu '%d'\n", d->domain_id, v->vcpu_id);
+            goto success;
+        }
+        v->arch.pmu_enabled = 0;
+        perf_count_active_vcpu--;
+        printk("H_PERFMON call disabled PMU for domain '%d' on vcpu '%d'\n",
+                d->domain_id, v->vcpu_id);
+    } else {
+        regs->gprs[3] = H_Parameter;
+    }
+
+success:
+    regs->gprs[3] = H_Success;
+    spin_unlock(&perf_pmu_lock);
+}
+
+__init_papr_hcall(H_PERFMON, h_perfmon);
index f9633ccfbd22ae32d83092d3c5a36871b0108d2b..acf5969c7a45d56c1f41ec1401796e47f9e9ddc6 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2005
+ * Copyright IBM Corp. 2005, 2007
  *
  * Authors: Jimi Xenidis <jimix@watson.ibm.com>
+ *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
  */
 
 #include <xen/config.h>
 #include <xen/lib.h>
 #include <xen/sched.h>
 #include <xen/mm.h>
+#include <xen/domain.h>
 #include <asm/current.h>
 
+void save_pmc_sprs(perf_sprs_t *p_sprs)
+{
+    p_sprs->mmcr0 = mfmmcr0();
+    p_sprs->mmcr1 = mfmmcr1();
+    p_sprs->mmcra = mfmmcra();
+    p_sprs->pmc[0] = mfpmc1();
+    p_sprs->pmc[1] = mfpmc2();
+    p_sprs->pmc[2] = mfpmc3();
+    p_sprs->pmc[3] = mfpmc4();
+    p_sprs->pmc[4] = mfpmc5();
+    p_sprs->pmc[5] = mfpmc6();
+    p_sprs->pmc[6] = mfpmc7();
+    p_sprs->pmc[7] = mfpmc8();
+}
+
+void load_pmc_sprs(perf_sprs_t *p_sprs)
+{
+    mtpmc1(p_sprs->pmc[0]);
+    mtpmc2(p_sprs->pmc[1]);
+    mtpmc3(p_sprs->pmc[2]);
+    mtpmc4(p_sprs->pmc[3]);
+    mtpmc5(p_sprs->pmc[4]);
+    mtpmc6(p_sprs->pmc[5]);
+    mtpmc7(p_sprs->pmc[6]);
+    mtpmc8(p_sprs->pmc[7]);
+    mtmmcra(p_sprs->mmcra);
+    mtmmcr1(p_sprs->mmcr1);
+    mtmmcr0(p_sprs->mmcr0);
+}
+
 void save_sprs(struct vcpu *v)
 {
     v->arch.timebase = mftb();
@@ -36,6 +68,11 @@ void save_sprs(struct vcpu *v)
     v->arch.dar = mfdar();
     v->arch.dsisr = mfdsisr();
 
+    if (v->arch.pmu_enabled) {
+        save_pmc_sprs(&(v->arch.perf_sprs));
+        v->arch.perf_sprs_stored = 1;
+    }
+
     save_cpu_sprs(v);
 }
 
@@ -50,6 +87,13 @@ void load_sprs(struct vcpu *v)
     mtdar(v->arch.dar);
     mtdsisr(v->arch.dsisr);
 
+    if (v->arch.pmu_enabled) {
+        if (v->arch.perf_sprs_stored)
+            load_pmc_sprs(&(v->arch.perf_sprs));
+        else
+            load_pmc_sprs(&perf_clear_sprs);
+    }
+
     load_cpu_sprs(v);
 
     /* adjust the DEC value to account for cycles while not
index 07e7217b6dc2fe59d3f0f8c06fa1436d12450a7b..9eec6d9d10b7e16cbe10543702f73937e5d5e837 100644 (file)
@@ -105,6 +105,12 @@ LOAD_GPRS "(\from+1)", \to, \uregs
     nop
 .endm
 
+.macro PMU_SAVE_STATE scratch
+    mfspr \scratch,SPRN_MMCR0             /* ensure MMCR0[FCH] is 1 */
+    ori \scratch,\scratch,MMCR0_FCH
+    mtspr SPRN_MMCR0, \scratch
+.endm
+
 .macro EXCEPTION_HEAD parea continue
     /* make room for cpu_user_regs */
     subi r1, r1, STACK_VOLATILE_AREA + UREGS_sizeof
@@ -156,7 +162,7 @@ LOAD_GPRS "(\from+1)", \to, \uregs
     ori r0, r0, MSR_RI@l
     mtmsrd r0
 
-
+    PMU_SAVE_STATE r0
 .endm
 
 /* For exceptions that use HSRR0/1 (preserving the OS's SRR0/1). */
@@ -183,6 +189,7 @@ LOAD_GPRS "(\from+1)", \to, \uregs
     ori r0, r0, MSR_RI@l
     mtmsrd r0
 
+    PMU_SAVE_STATE r0
 .endm
 
 /* Hypervisor exception handling code; copied to physical address zero. */
@@ -328,6 +335,12 @@ ex_fp:
     li r0, 0xe00 /* exception vector for GDB stub */
     bctr
 
+    . = 0xf00
+ex_perfmon:
+    GET_STACK r13 SPRN_SRR1
+    EXCEPTION_HEAD r13 ex_perfmon_continued
+    bctr
+
     .align 3
     .globl exception_vectors_end
 
@@ -452,6 +465,16 @@ ex_dec_continued:
     addi r1, r1, STACK_FRAME_OVERHEAD   /* restore stack to cpu_user_regs */
     b fast_resume
 
+ex_perfmon_continued:
+    EXCEPTION_SAVE_STATE r1
+    LOADADDR r12, do_perfmon
+    mr r3, r1                           /* pass pointer to cpu_user_regs */
+    subi r1, r1, STACK_FRAME_OVERHEAD   /* make a "caller" stack frame */
+    CALL_CFUNC r12
+
+    addi r1, r1, STACK_FRAME_OVERHEAD   /* restore stack to cpu_user_regs */
+    b fast_resume
+
 ex_hdec_continued:
     /* When we get an HDEC, we (almost?) always context_switch, so we need to
      * save the nonvolatiles.  */
index 58a1417de9909ec771c48b2d9532bfd7680c2076..957667ddec3a75c3cda43680ba4cf79170d5e621 100644 (file)
@@ -16,6 +16,7 @@
  * Copyright IBM Corp. 2005, 2007
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
  */
 
 #ifndef _ASM_DOMAIN_H_
 #include <asm/htab.h>
 #include <asm/powerpc64/ppc970.h>
 
+
+typedef struct {
+    ulong mmcr0;
+    ulong mmcr1;
+    ulong mmcra;
+    ulong pmc[NUM_PMCS];
+} perf_sprs_t;
+
+extern atomic_t perf_count_active;
+extern perf_sprs_t perf_clear_sprs;
+
 struct arch_domain {
     struct domain_htab htab;
 
@@ -84,7 +96,12 @@ struct arch_vcpu {
     ulong timebase;
     ulong dar;
     ulong dsisr;
-    
+
+    /* performance monitor sprs per vcpu */
+    int pmu_enabled;
+    int perf_sprs_stored;
+    perf_sprs_t perf_sprs;
+
     /* Segment Lookaside Buffer */
     struct slb_entry slb_entries[NUM_SLB_ENTRIES];
 
@@ -102,6 +119,8 @@ extern void full_resume(void);
 
 extern void save_sprs(struct vcpu *);
 extern void load_sprs(struct vcpu *);
+extern void save_pmc_sprs(perf_sprs_t *p_sprs);
+extern void load_pmc_sprs(perf_sprs_t *p_sprs);
 extern void save_segments(struct vcpu *);
 extern void load_segments(struct vcpu *);
 extern void save_float(struct vcpu *);
index 03679ca2faba9e1cf307266c878e6226d33f25bf..a04477ed1ed79b3acdc99d165dc88d9a70167127 100644 (file)
@@ -66,6 +66,7 @@
 #define H_IPOLL                 0x0070  /* Crit Yes             int     */
 #define H_XIRR                  0x0074  /* Crit Yes             int     */
 #define H_MIGRATE_PCI_TCE       0x0078  /* Norm Yes-if LRDR     migrate */
+#define H_PERFMON               0x007c  /* Norm Yes-if PMU      perfmon */
 #define H_CEDE                  0x00e0  /* Crit Yes             splpar  */
 #define H_CONFER                0x00e4
 #define H_PROD                  0x00e8
index fe43304e827b1f656dfe7622c558a22135c23d0a..152ba504ac108bb4334e784036cec851a80beaea 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2005, 2006
+ * Copyright IBM Corp. 2005, 2006, 2007
  *
  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
  */
 
 #ifndef _ASM_PROCESSOR_H_
@@ -200,6 +201,141 @@ static inline ulong mfr1(void)
     return r1;
 }
 
+static inline void mtmmcr0(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_MMCR0), "r"(val));
+}
+static inline ulong mfmmcr0(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_MMCR0));
+    return rval;
+}
+
+static inline void mtmmcr1(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_MMCR1), "r"(val));
+}
+static inline ulong mfmmcr1(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_MMCR1));
+    return rval;
+}
+
+static inline void mtmmcra(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_MMCRA), "r"(val));
+}
+static inline ulong mfmmcra(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_MMCRA));
+    return rval;
+}
+
+static inline void mtpmc1(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC1), "r"(val));
+}
+static inline ulong mfpmc1(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC1));
+    return rval;
+}
+
+static inline void mtpmc2(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC2), "r"(val));
+}
+static inline ulong mfpmc2(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC2));
+    return rval;
+}
+
+static inline void mtpmc3(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC3), "r"(val));
+}
+static inline ulong mfpmc3(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC3));
+    return rval;
+}
+
+static inline void mtpmc4(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC4), "r"(val));
+}
+static inline ulong mfpmc4(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC4));
+    return rval;
+}
+
+static inline void mtpmc5(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC5), "r"(val));
+}
+static inline ulong mfpmc5(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC5));
+    return rval;
+}
+
+static inline void mtpmc6(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC6), "r"(val));
+}
+static inline ulong mfpmc6(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC6));
+    return rval;
+}
+
+static inline void mtpmc7(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC7), "r"(val));
+}
+static inline ulong mfpmc7(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC7));
+    return rval;
+}
+
+static inline void mtpmc8(ulong val)
+{
+    asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC8), "r"(val));
+}
+static inline ulong mfpmc8(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC8));
+    return rval;
+}
+
+static inline ulong mfsdar(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_SDAR));
+    return rval;
+}
+
+static inline ulong mfsiar(void)
+{
+    ulong rval;
+    asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_SIAR));
+    return rval;
+}
+
 static inline void mtsprg0(ulong val)
 {
     __asm__ __volatile__ ("mtspr %0, %1" : : "i"(SPRN_SPRG0), "r"(val));
index 99a3ba2f5c6c6e03d2848797cfbe6aa703420505..f72e1591c4f20d7a14f3f9232da1f253e4c159cc 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
- * Copyright (C) IBM Corp. 2005
+ * Copyright IBM Corp. 2005, 2007
  *
  * Authors: Jimi Xenidis <jimix@watson.ibm.com>
+ *          Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
  */
 
 #ifndef _ASM_REG_DEFS_H_
 #define SPRN_LPCR   318
 #define SPRN_LPIDR  319
 
+/* Performance monitor spr encodings */
+#define SPRN_MMCRA  786
+#define   MMCRA_SAMPHV    UL(0x10000000) /* state of MSR HV when SIAR set */
+#define   MMCRA_SAMPPR    UL(0x08000000) /* state of MSR PR when SIAR set */
+#define   MMCRA_SAMPLE_ENABLE UL(0x00000001) /* enable sampling */
+#define NUM_PMCS 8
+#define SPRN_PMC1   787
+#define SPRN_PMC2   788
+#define SPRN_PMC3   789
+#define SPRN_PMC4   790
+#define SPRN_PMC5   791
+#define SPRN_PMC6   792
+#define SPRN_PMC7   793
+#define SPRN_PMC8   794
+#define SPRN_MMCR0  795
+#define   MMCR0_FC      UL(0x80000000) /* freeze counters */
+#define   MMCR0_FCS     UL(0x40000000) /* freeze in supervisor state */
+#define   MMCR0_FCP     UL(0x20000000) /* freeze in problem state */
+#define   MMCR0_FCM1    UL(0x10000000) /* freeze counters while MSR mark = 1 */
+#define   MMCR0_FCM0    UL(0x08000000) /* freeze counters while MSR mark = 0 */
+#define   MMCR0_PMAE    UL(0x04000000) /* performance monitor alert enabled */
+#define   MMCR0_PMAO    UL(0x00000080) /* performance monitor alert occurred */
+#define   MMCR0_FCH     UL(0x00000001) /* freeze conditions in hypervisor */
 #define SPRN_SIAR   796
 #define SPRN_SDAR   797
+#define SPRN_MMCR1  798
 
 /* As defined for PU G4 */
 #define SPRN_HID0   1008
index f9f52397dd6367481b88d2e44fb28a7669e0d324..3d17cc519323e9021fa8cd7e74ae12fd5ef3dbbb 100644 (file)
 #ifndef __ASM_PPC_XENOPROF_H__
 #define __ASM_PPC_XENOPROF_H__
 
-/* unimplemented */
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <public/xen.h>
+
+/* All the classic PPC parts use these */
+static inline unsigned int ctr_read(unsigned int i)
+{
+       switch(i) {
+       case 0:
+               return mfpmc1();
+       case 1:
+               return mfpmc2();
+       case 2:
+               return mfpmc3();
+       case 3:
+               return mfpmc4();
+       case 4:
+               return mfpmc5();
+       case 5:
+               return mfpmc6();
+       case 6:
+               return mfpmc7();
+       case 7:
+               return mfpmc8();
+       default:
+               return 0;
+       }
+}
+
+static inline void ctr_write(unsigned int i, unsigned int val)
+{
+       switch(i) {
+       case 0:
+               mtpmc1(val);
+               break;
+       case 1:
+               mtpmc2(val);
+               break;
+       case 2:
+               mtpmc3(val);
+               break;
+       case 3:
+               mtpmc4(val);
+               break;
+       case 4:
+               mtpmc5(val);
+               break;
+       case 5:
+               mtpmc6(val);
+               break;
+    case 6:
+        mtpmc7(val);
+        break;
+    case 7:
+        mtpmc8(val);
+        break;
+    default:
+        break;
+    }
+}
+
+static inline void print_perf_status()
+{
+    ulong mmcr0 = mfmmcr0();
+    ulong mmcr1 = mfmmcr1();
+    ulong mmcra = mfmmcra();
+    ulong sdar = mfsdar();
+    ulong siar = mfsiar();
+    printk("MMCR0 0x%0lX\n",mmcr0);
+    printk("MMCR1 0x%0lX\n",mmcr1);
+    printk("MMCRA 0x%0lX\n",mmcra);
+    printk("SIAR 0x%0lX\n",siar);
+    printk("SDAR 0x%0lX\n",sdar);
+}
 
 #endif